package com.licode.codekit.buildprj;

import com.intellij.util.ResourceUtil;
import com.licode.codekit.utils.FileUtil;
import com.licode.codekit.utils.PomFile;
import com.licode.codekit.utils.StrUtil;

import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.nio.charset.StandardCharsets;
import java.util.zip.ZipEntry;
import java.util.zip.ZipInputStream;

/**
 * @author licode
 */
public class ModuleBuilder {

    public ModuleBuilder() {
    }

    private String getRootDir(String dir) {
        String zipRoot = dir;
        if (dir != null && dir.length() >= 2) {
            if (!dir.endsWith("/")) {
                zipRoot = dir + "/";
            }

            return zipRoot;
        } else {
            return "";
        }
    }

    private String getTemplateFile(String createType) {
        if (CodeKitConf.MT_SINGLE_SIX.equals(createType)) {
            return "arch-module.zip";
        } else if (CodeKitConf.MT_SIMPLE_ARCH.equals(createType)) {
            return "sim-arch-module.zip";
        } else if (CodeKitConf.MT_SINGLE.equals(createType)) {
            return "single-module.zip";
        } else if (CodeKitConf.MT_SPEC_SIX.equals(createType)) {
            return "spec-arch-module.zip";
        } else if (CodeKitConf.MT_STARTER.equals(createType)) {
            return "starter.zip";
        } else if (CodeKitConf.MT_PARENT.equals(createType)) {
            return "module-parent.zip";
        } else {
            return "";
        }
    }

    private InputStream getTemplateStream(String createType) {
        return FileUtil.getResourceAsStream(getTemplateFile(createType));
    }

    private String calcPkgDir(ProjectContext prjCtx) {
        String pkgDir = CodeKitConf.SRC_ROOT_PREFIX + "/" + prjCtx.getPackageDir() + "/";
        return pkgDir.replace("//", "/");
    }

    public boolean buildModule(ProjectContext prjCtx, String createType) throws IOException {
        boolean buildRet = false;
        String moduleName = prjCtx.getModuleName();
        String moduleClassName = prjCtx.getModuleClassName();
        String srcRoot = prjCtx.getRootDir() + "/" + moduleName;
        String pkgDir = calcPkgDir(prjCtx);

        try (InputStream tempIs = getTemplateStream(createType);
             ZipInputStream zipIs = new ZipInputStream(tempIs, StandardCharsets.UTF_8)) {
            for (ZipEntry nextEntry = zipIs.getNextEntry();
                 nextEntry != null; nextEntry = zipIs.getNextEntry()) {
                String name = nextEntry.getName()
                        .replace("{module-name}", moduleName)
                        .replace("{module-class-name}", moduleClassName)
                        .replace(CodeKitConf.SRC_ROOT_PREFIX, pkgDir);
                String currDir = FileUtil.trimPath(srcRoot + "/" + name);
                File currFile = new File(currDir);

                if (nextEntry.isDirectory()) {
                    FileUtil.makeDirs(currFile);
                } else {
                    StrUtil.calcFilePackage(currDir, prjCtx);
                    handleModuleFile(prjCtx, zipIs, currFile);
                }

                zipIs.closeEntry();
            }

            prjCtx.addModule(moduleName);
            prjCtx.updatePomFile();

            buildRet = true;
        } catch(Exception e) {
            e.printStackTrace();
        }

        return buildRet;
    }

    private void handleModuleFile(ProjectContext prjCtx, ZipInputStream zipIs, File currFile) {
        String content = FileUtil.readText(zipIs, "utf-8");
        FileUtil.saveStrToFile(currFile,
                prjCtx.handleContent(content).getBytes(StandardCharsets.UTF_8));

        if (currFile.getAbsolutePath().endsWith("pom.xml")) {
            PomFile pomFile = new PomFile();
            pomFile.parse(currFile.getAbsolutePath());
            pomFile.save();
        }
    }
}
